from decimal import Decimal
from typing import Optional, Union
from datetime import datetime
from pydantic import BaseModel, validator, constr, ConfigDict


class CoreModel(BaseModel):
    """
    Any common logic to be shared by all models goes here
    """
    pass


class DateTimeModelMixin(BaseModel):
    created_at: Optional[datetime]
    updated_at: Optional[datetime]


class IDModelMixin(BaseModel):
    id: int


class UserBase(IDModelMixin):
    nickName: str
    avatarUrl: str
    gender: int
    token: str
    is_active: bool
    created_at: Optional[datetime] = None


class UserCreate(UserBase):
    password: str


class UserRegister(BaseModel):
    username: str
    password: str
    phone: str
    code: str


class UserPasswordUpdate(CoreModel):
    """
    Users can change their password
    """
    password: str
    salt: str

    model_config = ConfigDict(from_attributes=True)


class UserInDB(DateTimeModelMixin, UserBase):
    """
    Add in id, created_at, updated_at, and user's password and salt
    """
    password: str
    salt: str

    model_config = ConfigDict(from_attributes=True)


class UserPublic(DateTimeModelMixin, UserBase):
    model_config = ConfigDict(from_attributes=True)


class User(UserBase):
    id: int
    disabled: int
    is_superuser: int
    discount: float
    openid: Union[str, None]
    phone: Union[str, None]
    username: str
    gift: Decimal

    model_config = ConfigDict(from_attributes=True)


class UserOperationLog(DateTimeModelMixin):
    uid: str
    path: str
    method: str
    ip: str
    input: str

    model_config = ConfigDict(from_attributes=True)


class VipRecordBase(DateTimeModelMixin):
    pid: int
    uid: str
    status: Union[int, None] = None
    order_sn: str
    amount: float
    length: int

    model_config = ConfigDict(from_attributes=True)


class VipRecordInDB(IDModelMixin, VipRecordBase):
    model_config = ConfigDict(from_attributes=True)


class RolesInDB(DateTimeModelMixin):
    order_sn: str
    amount: float
    length: int
    model_config = ConfigDict(from_attributes=True)
